package cn.com.wxd.biz.website;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.com.wxd.dao.website.ArticleDao;
import cn.com.wxd.entity.website.ArticleInfo;
import cn.com.wxd.service.index.IndexEntity;
import cn.com.wxd.service.index.IndexFile;
import cn.com.wxd.service.index.IndexSearch;
import cn.com.wxd.common.CharUtil;
import cn.com.wxd.common.DateUtil;
import cn.com.wxd.common.PageInfo;
import cn.com.wxd.util.dao.QueryParamHeper;
import cn.com.wxd.common.data.KVMap;
import cn.com.wxd.common.data.KeyValue;
import cn.com.wxd.common.file.MyFileUtil;
import cn.com.wxd.util.website.WebsiteInfo;

/**
 * Title:ArticleServiceImpl.java
 * Description:cn.com.wxd.biz.article
 * <p>
 * Company: Amumu管理平台
 * Copyright: Copyright (c) 2015
 * All right reserved.
 * Created time: 2015-11-24 下午6:13:44
 *
 * @author WangXuDong
 * @version 1.0
 */
public class ArticleServiceImpl implements ArticleService {
    private ArticleDao articleDao;
    private static final Logger log = LoggerFactory.getLogger(ArticleServiceImpl.class);

    @Override
    public List<ArticleInfo> getArticlesFromDb(String caid, PageInfo page) {
        if (page == null) {
            page = new PageInfo();
        }
        return articleDao.selectArticlesByCaid(CharUtil.stringParsInt(caid), page);
    }

    @Override
    public List<ArticleInfo> getArticles(String caid, PageInfo page) {
        if (CharUtil.isEmpty(caid)) {
            return null;
        }
        if (page == null) {
            page = new PageInfo();
        }
        if (WebsiteInfo.isCache()) {
            // 如果获取文章的数量没超过缓存
            if (page.getPageIndex() * page.getPageSize() < WebsiteInfo.getCacheMaxCount()) {
                // 从缓存中获取数据
                List<ArticleInfo> lis = WebsiteCache.getWebsiteCache().get(CharUtil.stringParsInt(caid));
                List<ArticleInfo> relis = new ArrayList<>();
                if (lis != null) {
                    page.setTotalCount(lis.size());
                    int ilen = (page.getPageIndex() - 1) * page.getPageSize();
                    for (int i = ilen; i < lis.size(); i++) {
                        relis.add(lis.get(i));
                        if (i == page.getPageIndex() * page.getPageSize() - 1) {
                            break;
                        }
                    }
                } else {
                    WebsiteCache.refreshCache(CharUtil.stringParsInt(caid));
                    relis = getArticlesFromDb(caid, page);
                }
                return relis;
            }
        }
        return getArticlesFromDb(caid, page);
    }

    @Override
    public boolean saveArticle(ArticleInfo articleInfo) {

        IndexEntity ie = new IndexEntity();
        IndexFile inf = new IndexFile();
        String confPath = WebsiteInfo.getArticleIndexPath();
        //初始化建立索引的javaBean

        if (!CharUtil.isEmpty(articleInfo.getIndexId())) {
            ie.setId(articleInfo.getIndexId());
            ie.setContent(articleInfo.getTitle() + articleInfo.getAuthor() + articleInfo.getContentText());
            HashMap<String, String> map = new HashMap<>(); //设置其他的属性，用于搜索
            map.put("title", articleInfo.getTitle());
            map.put("author", articleInfo.getAuthor());
            ie.setOtherParam(map);
            List<IndexEntity> list = new ArrayList<>();
            list.add(ie);  //加入集合中用于创建时参数
            try {
                if (articleInfo.getContentText() != null && !(articleInfo.getContentText().trim().equals(""))) {
                    inf.update(list.get(0), confPath);   //如果索引已近存在，就重新更新索引
                }
            } catch (Exception e) {
                log.error("异常:索引创建失败！" + e.getMessage(), e);
            }
        } else {
            articleInfo.setIndexId(DateUtil.getTimestamp() + CharUtil.getRanNumber(4)); //设置索引
            ie.setId(articleInfo.getIndexId());
            ie.setContent(articleInfo.getTitle() + articleInfo.getAuthor() + articleInfo.getContentText());
            HashMap<String, String> map = new HashMap<>(); //设置其他的属性，用于搜索
            map.put("title", articleInfo.getTitle());
            map.put("author", articleInfo.getAuthor());
            ie.setOtherParam(map);
            List<IndexEntity> list = new ArrayList<>();
            list.add(ie);  //加入集合中用于创建时参数
            // 进行索引的创建
            if (articleInfo.getContentText() != null && !(articleInfo.getContentText().trim().equals(""))) {
                try {
                    inf.buildIndex(list, confPath);//若不存在创建新索引。
                } catch (Exception e) {
                    log.error("异常:索引创建失败！" + e.getMessage(), e);
                }
                //创建索引结束
            }
        }
        if (CharUtil.isEmpty(articleInfo.getDateTime())) {
            articleInfo.setDateTime(DateUtil.getDateStr());
        }
        if (CharUtil.isEmpty(articleInfo.getType())) {
            articleInfo.setType("A");
        }
        if (articleInfo.getOrderId() == 0) {
            articleInfo.setOrderId((articleDao.selectMaxOrderId() + 1));  //设置最大排序的值
        }
        if (articleDao.insertArticle(articleInfo)) {
            //刷新缓存
            if (WebsiteInfo.isCache()) {
                WebsiteCache.refreshCache(articleInfo.getCaId());
            }
            return true;
        }
        return false;
    }

    @Override
    public boolean deleteArticle(String id) {
        ArticleInfo ai;
        ai = articleDao.selectArticleById(CharUtil.stringParsInt(id));
        // 删除索引
        IndexFile inf = new IndexFile();
        String confPath = WebsiteInfo.getArticleIndexPath();
        try {
            inf.deleteIndex(new String[] {ai.getIndexId()}, confPath);
        } catch (Exception e) {
            log.error("索引删除出错" + e.getMessage());
        }
        if (articleDao.deleteArticle(CharUtil.stringParsLong(id))) {
            //刷新缓存
            if (WebsiteInfo.isCache()) {
                WebsiteCache.refreshCache(ai.getCaId());
            }
            return true;
        }
        return false;
    }

    @Override
    public ArticleInfo getArticle(String id, boolean isAddClick) {
        if (id != null && !(id.trim().equals(""))) {
            if (isAddClick) {
                HashMap<String, String> map = new HashMap<>();
                map.put("id", id);
                if (!articleDao.updateClickQuan(map)) {
                    log.error("文章添加点击量失败！");
                }
            }
            ArticleInfo ai = articleDao.selectArticleById(CharUtil.stringParsInt(id));
            return ai;
        }
        return new ArticleInfo();
    }

    /**
     * 根据文章条件获取相关文章
     *
     * @param articleInfo 文章信息
     *
     * @return 文章
     */
    @Override
    public List<ArticleInfo> getArticle(ArticleInfo articleInfo, int maxCount) {

        KVMap<String, Object> map = new KVMap<>();
        KVMap<String, String> order = new KVMap<>();
        order.put("orderId", "desc");
        if (!CharUtil.isEmpty(articleInfo.getAuthor())) {
            map.put("author", articleInfo.getAuthor());
        }
        if (!CharUtil.isEmpty(articleInfo.getState())) {
            map.put("state", articleInfo.getState());
        }
        if (!CharUtil.isEmpty(articleInfo.getType())) {
            map.put("type", articleInfo.getType());
        }
        return articleDao.selectArticle(map, order, null, new PageInfo(1, maxCount));
    }

    /**
     * 批量删除文章
     *
     * @param ids 文章ID 使用"/"分割
     *
     * @return
     */
    @Override
    public boolean batchDeleteA(String ids) {
        String[] idstr = ids.split("/");
        long[] idints = new long[idstr.length];
        String[] indexidints = new String[idstr.length];
        int caid = -1;
        int i = 0;
        List<ArticleInfo> articleInfos = articleDao.selectArticleByids(idstr);
        for (ArticleInfo articleInfo : articleInfos) { //获取索引号和栏目号
            idints[i] = articleInfo.getId();
            caid = articleInfo.getCaId();
            indexidints[i] = articleInfo.getIndexId();  //保存索引id
            i++;
        }
        IndexFile inf = new IndexFile();
        try {
            inf.deleteIndex(indexidints, WebsiteInfo.getArticleIndexPath());//根据索引ID数组删除索引
        } catch (Exception e) {
            log.error("索引删除异常!" + e.getMessage());
        }
        if (idints.length <= 0) {
            return false;
        }
        boolean result = articleDao.deleteArticles(idints);
        //刷新缓存
        if (caid >= 0 && WebsiteInfo.isCache()) {
            WebsiteCache.refreshCache(caid);
        }
        return result;
    }

    /**
     * 重建全文索引
     */
    @Override
    public boolean reBuildIndex() {
        //重建全文索引，先删除所有的文章索引
        String confPath = WebsiteInfo.getArticleIndexPath();
        IndexFile inf = new IndexFile();
        File file = new File(confPath);
        boolean bool = false;
        int cou = 0;
        if (file.exists()) {
            try {
                bool = MyFileUtil.deleteAllFilesOfDir(file);  // 删除文件夹，及其子文件
            } catch (IOException e) {
                log.error("没有权限删除文件夹，文件地址：" + file.getAbsolutePath() + ",请手动删除！");
            }
            while (!bool) {
                cou++;
                try {
                    bool = MyFileUtil.deleteAllFilesOfDir(file);
                } catch (IOException e) {
                    log.error("没有权限删除文件夹，文件地址：" + file.getAbsolutePath() + ",请手动删除！");
                }
                if (cou >= 10) {   //尝试10次删除文件失败后就相当于重建失败
                    return false;
                }
            }
            System.gc();//提示系统进行资源回收
        }

        PageInfo pageInfo = new PageInfo(1, 1000); // 默认1000条数据进行分页建立
        // 使用分页查询然后进行重建索引
        List<ArticleInfo> list = articleDao.selectArticles(pageInfo);
        List<IndexEntity> ielist;
        int pagecount = pageInfo.getPageCount();
        for (int co = 0; co < pagecount; co++) {
            if (co > 0) {
                pageInfo.setPageIndex(co + 1);
                list = articleDao.selectArticles(pageInfo);
            }
            ielist = new ArrayList<>();
            // 开始分页式的查询并建立索引
            if (list != null && list.size() > 0) {   //初始创建索引所需的数据
                for (int i = 0; i < list.size(); i++) {
                    if (CharUtil.isEmpty(list.get(i).getContentText())) {
                        continue;
                    }
                    IndexEntity ie = new IndexEntity();
                    ie.setId(list.get(i).getIndexId());
                    ie.setContent(list.get(i).getContentText());
                    HashMap<String, String> map = new HashMap<String, String>(); // 设置其他的属性，用于搜索
                    map.put("title", list.get(i).getTitle());
                    map.put("author", list.get(i).getAuthor());
                    ielist.add(ie);
                }
                try {
                    if (ielist.size() > 0) {
                        inf.buildIndex(ielist, confPath); // 创建索引。
                    }
                } catch (Exception e) {
                    log.error("重建索引失败   原因：" + e.getMessage(), e);
                    return false;
                }
                ielist.clear();
                list.clear();
            }
        }
        log.info("全文索引已经创建成功!");
        return true;
    }

    @Override
    public List<ArticleInfo> getArticleByIndexId(String[] indexIds) {
        if (indexIds.length <= 0) {
            return null;
        }
        return articleDao.selectArticleByIndexId(indexIds);
    }

    @Override
    public boolean rankArticle(String newOrderId, String oldOrderId) {
        ArticleInfo ai = articleDao.selectArticleByOrderId(CharUtil.stringParsInt(oldOrderId));
        int newOrdId = CharUtil.stringParsInt(newOrderId);
        int oldOrdId = CharUtil.stringParsInt(oldOrderId);
        if (newOrdId == -1 || oldOrdId == -1) {
            return false;
        } else if (newOrdId == oldOrdId) {
            return true;
        } else {
            if (articleDao.updateOrder(newOrdId, oldOrdId)) {  //开始数据库中替换排序号
                //刷新缓存
                if (WebsiteInfo.isCache()) {
                    WebsiteCache.refreshCache(ai.getCaId());
                }
                return true;
            }
            return false;
        }
    }

    @Override
    public List<ArticleInfo> searchArticle(String searchType,
                                           KeyValue<String, String> searchKeyWord, PageInfo page) {
        if (CharUtil.isEmpty(searchKeyWord.getValue())) {
            return new ArrayList<>();
        }
        if (searchType != null && searchType.trim().equalsIgnoreCase("DB")) { //从数据库查询
            KVMap<String, Object> parm = new KVMap<>();  //设置参数
            parm.put(searchKeyWord.getKey(), searchKeyWord.getValue());
            ArrayList<String> fuzz = new ArrayList<>();
            fuzz.add(searchKeyWord.getKey());
            return articleDao.selectArticle(parm, null, fuzz, page);  //从数据库模糊查询

        } else if (searchType != null && searchType.trim().equalsIgnoreCase("IN")) {   //从索引查询
            IndexSearch is = new IndexSearch();
            String[] dataStr = null;
            page.setTotalCount(256);  //设置最大记录数为356条
            try {
                dataStr =
                        is.search(searchKeyWord.getValue(), WebsiteInfo.getArticleIndexPath(), "id", page.getPageSize(),
                                page.getPageIndex());
            } catch (Exception e) {
                log.error("从索引中搜索出现异常!" + e.getMessage(), e);
            }
            if (dataStr != null && dataStr.length > 0) {
                return articleDao.selectArticleByIndexId(dataStr);  //根据INDEX从数据库查
            }
        }
        return null;
    }

    @Override
    public int getArtirlCount() {
        return articleDao.selectArticleCount();
    }

    @Override
    public boolean moveArticle(String ids, String caid) {
        String[] idstr = ids.split("/");
        long[] idints = new long[idstr.length];
        int ordcaid = -1;
        for (int i = 0; i < idstr.length; i++) {
            idints[i] = CharUtil.stringParsLong(idstr[i]);    //转换为int类型
            if (i == 0) {
                ordcaid = articleDao.selectArticleById(idints[i]).getCaId();
            }
        }
        if (idints.length <= 0) {
            return false;
        }
        //刷新缓存
        boolean issuccess = articleDao.updateArticleCaid(idints, CharUtil.stringParsInt(caid));
        if (ordcaid >= 0 && WebsiteInfo.isCache() && issuccess) {
            WebsiteCache.refreshCache(ordcaid);
            WebsiteCache.refreshCache(CharUtil.stringParsInt(caid));
        }
        return issuccess;
    }

    @Override
    /**
     * 批量复制文章
     * @param ids 文章ID字符串用/隔开
     * @param caid 栏目号
     * @return 是否成功
     */
    public boolean cloneArticle(String ids, String caid) {
        String[] idstr = ids.split("/");
        List<ArticleInfo> artlists = articleDao.selectArticleByids(idstr);
        long maxOrderid = articleDao.selectMaxOrderId();
        if (artlists != null) {
            for (int i = 0; i < artlists.size(); i++) {
                ArticleInfo articleInfo = artlists.get(i);
                articleInfo.setOrderId(maxOrderid + i + 1);  //更改排序号，防止排序号重复
                articleInfo.setIndexId(DateUtil.getTimestamp() + CharUtil.getRanNumber(4));
                articleInfo.setCaId(CharUtil.stringParsInt(caid));
                //开始添加索引
                IndexEntity ie = new IndexEntity();
                IndexFile inf = new IndexFile();
                String confPath = WebsiteInfo.getArticleIndexPath();
                //初始化建立索引的javaBean
                ie.setId(articleInfo.getIndexId());
                ie.setContent(articleInfo.getTitle() + articleInfo.getAuthor() + articleInfo.getContentText());
                HashMap<String, String> map = new HashMap<>(); //设置其他的属性，用于搜索
                map.put("title", articleInfo.getTitle());
                map.put("author", articleInfo.getAuthor());
                ie.setOtherParam(map);
                List<IndexEntity> list = new ArrayList<>();
                list.add(ie);  //加入集合中用于创建时参数

                // 进行索引的创建
                if (articleInfo.getContentText() != null && !(articleInfo.getContentText().trim().equals(""))) {
                    try {
                        inf.buildIndex(list, confPath);//创建新索引。
                    } catch (Exception e) {
                        log.error("异常:索引创建失败！", e);
                    }
                    // 创建索引结束
                }

            }
            // 批量插入文章
            boolean issuccess = articleDao.insertArticles(artlists);
            // 刷新缓存
            if (CharUtil.stringParsInt(caid) >= 0 && WebsiteInfo.isCache() && issuccess) {
                // 更新目标栏目的内容
                WebsiteCache.refreshCache(CharUtil.stringParsInt(caid));
            }
            return issuccess;
        } else {
            return false;
        }
    }

    @Override
    public KVMap<String, List<ArticleInfo>> batchQueryArticle(List<QueryParamHeper> listqph) {
        KVMap<String, List<ArticleInfo>> map = articleDao.selectArticleBatch(listqph);
        for (int i = 0; i < map.size(); i++) {
            for (int j = 0; j < map.getValueIndex(i).size(); j++) {  //TODO 内容不作为数据进行放置到前台，减少流量
                map.getValueIndex(i).get(j).setContent("");
                map.getValueIndex(i).get(j).setContentText("");
            }
        }
        return map;
    }

    @Override
    /**
     * 根据一些文章的参数查文章
     */
    public List<ArticleInfo> getArticleByParam(KVMap<String, Object> param, KVMap<String, String> order,
                                               List<String> fuzzField, PageInfo page) {
        return articleDao.selectArticle(param, order, fuzzField, page);
    }

    @Override
    /**
     * 获取下一篇文章
     */
    public ArticleInfo getNextArt(int orderId, int caid) {
        if (orderId == -1 || caid == -1) {
            return null;
        }
        /**
         * 从缓存中获取
         */
        if (WebsiteInfo.isCache()) {
            List<ArticleInfo> list = WebsiteCache.getWebsiteCache().get(caid);
            if (list != null) {
                long[] cha = new long[list.size()];
                long ca;
                for (int i = 0; i < list.size(); i++) {
                    ca = orderId - list.get(i).getOrderId(); //获取排序号的差存在于临时数组中
                    cha[i] = ca;
                }
                Arrays.sort(cha);          //对数组排序
                for (int i = 0; i < cha.length; i++) {
                    if (cha[i] > 0) {
                        return list.get(i);  //获取非负数和0除外最小的一个。
                    }
                }
            }

        }
        return articleDao.selectNextArt(orderId, caid);
    }

    @Override
    /**
     * 获取上一篇文章
     */
    public ArticleInfo getPrevArt(int orderId, int caid) {
        if (orderId == -1 || caid == -1) {
            return null;
        }
        if (WebsiteInfo.isCache()) {
            List<ArticleInfo> list = WebsiteCache.getWebsiteCache().get(caid);
            if (list != null) {
                long[] cha = new long[list.size()];
                long ca;
                for (int i = 0; i < list.size(); i++) {
                    ca = list.get(i).getOrderId() - orderId; //获取排序号的差存在于临时数组中
                    cha[i] = ca;
                }
                Arrays.sort(cha);          //对数组排序
                for (int i = 0; i < cha.length; i++) {
                    if (cha[i] > 0) {
                        return list.get(i);  //获取非负数和0除外最小的一个。
                    }
                }
            }

        }
        return articleDao.selectPrevArt(orderId, caid);
    }

    @Override
    public ArticleInfo getArticleByOrderId(int OrderId) {
        return articleDao.selectArticleByOrderId(OrderId);
    }

    public void setArticleDao(ArticleDao articleDao) {
        this.articleDao = articleDao;
    }
}
